package settings

import (
	"fmt"
	"github.com/fsnotify/fsnotify"
	"github.com/spf13/viper"
)

type AppConfig struct {
	Name         string `mapstructure:"name"`
	Mode         string `mapstructure:"mode"`
	Port         int    `mapstructure:"port"`
	Version      string `mapstructure:"version"`
	StartTime    string `mapstructure:"start_time"`
	MachineID    int    `mapstructure:"machine_id"`
	*LogConfig   `mapstructure:"zaplog"`
	*MySQLConfig `mapstructure:"mysql"`
	*RedisConfig `mapstructure:"redis"`
}

type MySQLConfig struct {
	Host         string `mapstructure:"host"`
	User         string `mapstructure:"user"`
	Password     string `mapstructure:"password"`
	DB           string `mapstructure:"dbname"`
	Port         int 	`mapstructure:"port"`
	MaxOpenCons  int 	`mapstructure:"max_open_conns"`
	MaxIdleCons  int 	`mapstructure:"max_idle_conns"`
	ConnectMaxLifeTime  int    	`mapstructure:"connection_max_life_time"`
}

type RedisConfig struct {
	Host         string `mapstructure:"host"`
	Password     string `mapstructure:"password"`
	Port         int    `mapstructure:"port"`
	DB           int    `mapstructure:"db"`
	PoolSize     int `mapstructure:"pool_size"`
	MinIdleConns  int `mapstructure:"min_idle_conns"`
}

type LogConfig struct {
	Level      string `mapstructure:"level"`
	Filename   string `mapstructure:"filename"`
	MaxSize    int    `mapstructure:"max_size"`
	MaxAge     int    `mapstructure:"max_age"`
	MaxBackups int    `mapstructure:"max_backup"`
}

const (
	defaultConfigureName = "config" // 配置文件的文件名,没有扩展名,如.yaml,.toml这样的扩展名
	defaultConfigureType = "yaml"   // 设置文件扩展名,另外如果配置文件的名称没有扩展名,则需要配置这个选项
	defaultConfigurePath = "./conf/"
	defaultConfigFile 	 = "./conf/config.yaml"
)

var appConfig = &AppConfig{}

// Get 获取整个配置
func Get() *AppConfig{
	return appConfig
}

// init 包级别初始化函数
func init(){
	initAppConfig()
}

// initAppConfig 初始化整个应用程序的配置, 读取配置文件
func initAppConfig() {
	viper.SetConfigName(defaultConfigureName)
	viper.SetConfigType(defaultConfigureType)
	viper.AddConfigPath(defaultConfigurePath)
	viper.SetConfigFile(defaultConfigFile)

	// 监控配置和重新获取配置
	viper.WatchConfig()
	viper.OnConfigChange(func(e fsnotify.Event) {
		fmt.Println("配置文件发生改变，正在重新读取...")
		readConfigFile()
		fmt.Println("读取成功")
	})

	readConfigFile()
}

// readConfigFile 读取配置文件中的内容
func readConfigFile() {
	if err := viper.ReadInConfig(); err != nil {
		if _, ok := err.(viper.ConfigFileNotFoundError); ok {
			// Config file not found; ignore error if desired
			fmt.Println("配置文件没有找到！",err.Error())
		} else {
			// Config file was found but another error was produced
			fmt.Println("配置文件已经找到，但是发生未知错误！",err.Error())
			panic(any(err))
		}
		panic(any(err))
	}

	// 将整个配置文件反序列化到结构体
	err := viper.Unmarshal(appConfig)
	if err != nil {
		fmt.Println("配置文件反序列失败", err)
		panic(any(err))
	}
}